package cn.kz.hrm.service.impl;

import cn.kz.hrm.commonfeiclient.CommonFeignClient;
import cn.kz.hrm.config.RegisterConfigPropertis;
import cn.kz.hrm.dto.PhoneRegisterCode;
import cn.kz.hrm.service.IVerifycodeService;
import cn.kz.hrm.util.*;
import cn.kz.hrm.vo.SMSCodeSendVo;
import cn.kz.krm.myexceptions.MyGlobalExceptions;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;


@Service
public class VerifycodeServiceImpl implements IVerifycodeService {

    //打印日志
    private Logger logger = LoggerFactory.getLogger(VerifycodeServiceImpl.class);

    //获取手机验证码的存储redis的key值的前缀
    public static final String PHONE_REGISTER_CODE_REDIS = "REGISTER:PHONE:";


    @Autowired
    private CommonFeignClient commonFeignClient;

    @Autowired
    private RegisterConfigPropertis registerConfigPropertis;

    /**
     * 生成图片验证码，同时将生成的验证码的值，存入到redis中，方便做判断。
     * @param imageCodeKey
     * @return
     */
    @Override
    public String getImageCode(String imageCodeKey) {
        //1、判断参数是否为null
        if (StringUtils.isBlank(imageCodeKey)) {
            throw new MyGlobalExceptions("无效的key！请重新传入！");
        }
        //2、生成一个验证码的值，4位的验真码，截取一段。
        String codeStr = UUID.randomUUID().toString().substring(0, 4);
        //3、将验证码的值存入redis中，imageCodeKey作为key存入，验证码的值为value,设置过期时间为600秒
        commonFeignClient.setRedisOutTime(imageCodeKey, registerConfigPropertis.getCodeeouttime(), codeStr);
        //4、将验证码的值存入到图片中个，利用工具类
        try {
            String verifyCode = VerifyCodeUtils.VerifyCode(registerConfigPropertis.getCodewidth(), registerConfigPropertis.getCodeheight(), codeStr);
            return verifyCode;
        } catch (IOException e) {
            e.printStackTrace();
            throw new MyGlobalExceptions("创建图片验证码失败！");
        }
    }

    /**
     * 获取手机验证码
     * @param phoneRegisterCode
     */
    @Override
    public void getSmsCode(PhoneRegisterCode phoneRegisterCode) {
        //图片验证码
        String imageCode = phoneRegisterCode.getImageCode();
        //图片存储到redis中的key值
        String imageCodeKey = phoneRegisterCode.getImageCodeKey();
        //手机号
        String mobile = phoneRegisterCode.getMobile();
//1、todo 判断参数的合法性
        if (StringUtils.isBlank(mobile)) {
            throw new MyGlobalExceptions("手机号不能为空，请重新输入！！");
        }
        if (StringUtils.isBlank(imageCode)) {
            throw new MyGlobalExceptions("请输入图片验证码！");
        }
        if (StringUtils.isBlank(imageCodeKey)) {
            throw new MyGlobalExceptions("无效的key！请刷新页面重试！");
        }
//2、todo 获取图片验证码中的值，与redis中的值进行比对，判断是否正确，去掉前后的空格
        AjaxResult ajaxResult = commonFeignClient.getRedis(imageCodeKey);

        //判断是否取到redis中的值
        if (ajaxResult.getResultObj() == null || !ajaxResult.isSuccess()) {//没有获取到redis的值，同时
            throw new MyGlobalExceptions("找不到redis的值，或者已过期，请重新获取！！");
        }
        //存储进入的是object的对，所以要转换为string对象
        String ajaxResultStr = ajaxResult.getResultObj().toString();
        //判断验证码的值是否是与存储的redis中的值一致。注意大小写
        if (!ajaxResultStr.equals(imageCode.toLowerCase())) {
           throw new MyGlobalExceptions("验证码错误，请输入正确的验证码！");
        }
//3、todo 生成手机验证码，
        Date dateNow = new Date();
        //3.1.上一次有，获取上一次存入的redis中的值，//register中的key值
        String codeToRedisKey = PHONE_REGISTER_CODE_REDIS + mobile;
        AjaxResult phoneRegisterCodeToRedis = commonFeignClient.getRedis(codeToRedisKey);
        //3.1.1.判断时候是否过了重发时间 ：当前时间 - 上一次发送时间 > 60s
        //手机验证码
        String phoneRegisterCodeValue = null;

        if (phoneRegisterCodeToRedis.isSuccess() && phoneRegisterCodeToRedis.getResultObj() != null) {//证明是已经获取到redis中的value值，
            //将value值进行转换成SMSCodeSendVo对象，该类中封装了value中参数
            String valueToRedis = phoneRegisterCodeToRedis.getResultObj().toString();
            SMSCodeSendVo smsCodeSendVo = JSONObject.parseObject(valueToRedis, SMSCodeSendVo.class);
            //3.1.2.如果没过重发时间 - 报错
            if ((dateNow.getTime() - smsCodeSendVo.getSendTime().getTime()) / 1000 < 60) {
                //throw new MyGlobalExceptions("请勿频繁发送验证码，请稍后再试！");
                throw new MyGlobalExceptions("请勿频繁发送验证码，请稍后再试！");
            }
            //3.1.3.如果过了重发时间 ，再次使用上一次验证码的值
            phoneRegisterCodeValue = smsCodeSendVo.getCode();
        } else {
            //3.2.上一次没有，
            //3.2.1.创建一个手机验证码，调用工具类生成一个验证码,4位数
            phoneRegisterCodeValue = StrUtils.getRandomString(registerConfigPropertis.getCodelength());
        }
//4、todo 将数据保存到redis中
        //4.1将数据转换成json格式
        String phoneCodeStrToRedisValue = JSONObject.toJSONString(new SMSCodeSendVo(phoneRegisterCodeValue, dateNow));

        //调用接口进行封装redis，key time value，参数值
        AjaxResult ajaxResult1SaveToRedis = commonFeignClient.setRedisOutTime(codeToRedisKey, registerConfigPropertis.getCodeeouttime(), phoneCodeStrToRedisValue);
        if (!ajaxResult1SaveToRedis.isSuccess()) {
            logger.error("手机注册验证码存储redis失败！！");
            throw new MyGlobalExceptions("手机验证码存储失败！！");
        }

//5、todo 调用短信接口实现发送短信。
        //准备发送短信的消息
        String message = "尊敬的用户你的注册验证码为：" + phoneRegisterCodeValue + ",请在" + registerConfigPropertis.getCodeeouttime() / 60 + "分钟以内进行使用，同时请勿向他人泄露验证码信息！";
        //调用sms短信接口发送短信
        //短信网关地址
        String url = "http://utf8.api.smschinese.cn/";
        Map<String,String> map = new HashMap<>();
        map.put("Uid","蔠嚸kangz");
        map.put("Key","d41d8cd98f00b204e980");
        map.put("smsMob",mobile);
        map.put("smsText",message);
        //调用短信接口返回的值，
//        String result = SMSRegisterCodeUtil.sendPost(url, map);
//        //将短信接口的值，与接口中的值进行作比较，然后判断异常信息！
//        WebchineseSMSResult.checkResult(result);
        //输出信息发送的信息，查看验证码
        System.out.println(message);
 //6、todo 将发送的验证码的信息存储到sql表中
        //System.out.println(request.getRemoteAddr());//获取注册用户的ip地址。
    }
}
